package com.hooya.fa.eu.biz.business.service;


import com.hooya.fa.eu.biz.dao.entity.StkOrigDataCollect;
import com.hooya.fa.eu.biz.dao.entity.dto.BsDataDTO;
import com.hooya.fa.eu.biz.dao.mapper.MetaStkCustomsMapper;
import com.hooya.fa.eu.biz.dao.mapper.StkOrigDataCollectMapper;
import com.hooya.fa.eu.biz.dao.mapper.stk.TempPkpyMapper;
import com.hooya.fa.eu.biz.service.impl.CommonService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class Insert_BS {

    @Autowired
    private StkOrigDataCollectMapper stkOrigdataCollectMapper;

    @Autowired
    private TempPkpyMapper tempPkpyMapper;

    @Autowired
    private MetaStkCustomsMapper mataStkCustomsMapper;

    @Autowired
    private CommonService commonService;

    @Transactional
    public void insert_bs(String start) {
        try {
			log.info("开始执行Insert_BS");
            // 处理日期
            Map<String, String> dateMap = commonService.dateChange(start);
            String beginDate = dateMap.get("currMonthStart");
            String nextDate = dateMap.get("nextMonthStart");
            String endDate = dateMap.get("currMonthEnd");

            // 获取主要数据
            List<BsDataDTO> mainData = tempPkpyMapper.getBsData(beginDate, nextDate);
            mainData.forEach(f->f.setIndex(f.getCpbh()+"|"+f.getDate()+"|"+f.getBelongs()+"|"+f.getAbbrbelongs()));

            //py中的index 他的区分是 cpbh+date 做键进行区分的
            //准备主要数据
            List<BsDataDTO> cutMainData = mainData.stream().map(f -> {
                BsDataDTO result = new BsDataDTO();
                result.setSku(f.getCpbh());
                result.setInoutDate(f.getDate());
                result.setBelongs(f.getBelongs());
                result.setAbbrbelongs(f.getAbbrbelongs());
                result.setIndex(f.getIndex());
                return result;
            }).collect(Collectors.toList());
            //走到这一步 就是sku+inoutDate进行区分 index  就是cutMainData的index

            // 添加价格
            Map<String, Object> priceResult = addPrice(cutMainData, endDate);
            List<BsDataDTO> withPriceData = (List<BsDataDTO>) priceResult.get("withPrice");
            List<BsDataDTO> withoutPriceData = (List<BsDataDTO>) priceResult.get("withoutPrice");

            // 添加异常价格
            List<BsDataDTO> abWithPriceData = addAbnormalPrice(withoutPriceData, endDate);

            // 合并所有价格数据
            List<BsDataDTO> allPriceData = new ArrayList<>();
            allPriceData.addAll(withPriceData);
            allPriceData.addAll(abWithPriceData);

            Map<String, List<BsDataDTO>> allPriceDataMap = allPriceData.stream().collect(Collectors.groupingBy(f -> f.getSku() + "|" + f.getIndex()));

            //merge -->  mainData数据和plnPriceData数据
            List<BsDataDTO> mergeData = new ArrayList<>();
            for (BsDataDTO mainItem : mainData) {
                String key = mainItem.getCpbh() + "|" + mainItem.getIndex();
                if (allPriceDataMap.containsKey(key)) {
                    List<BsDataDTO> bsDataDTOS = allPriceDataMap.get(key);
                    bsDataDTOS.forEach(f -> {
                        BsDataDTO newItem = new BsDataDTO();
                        BeanUtils.copyProperties(mainItem, newItem);
                        newItem.setInvoicedate(f.getInvoicedate());
                        newItem.setCurrency(f.getCurrency());
                        newItem.setPrice(f.getPrice());
                        mergeData.add(newItem);
                    });
                } else {
                    mergeData.add(mainItem);
                }
            }
            //无用数据不使用即可 -- 不必删除

            // 验证数据
            commonService.dataVerificationBs(mergeData);

            // 拆分有价格和无价格的数据
            List<BsDataDTO> finalWithPrice = mergeData.stream().filter(f -> f.getPrice() != null).collect(Collectors.toList());
            List<BsDataDTO> finalWithoutPrice = mergeData.stream().filter(f -> f.getPrice() == null).collect(Collectors.toList());

            // 转换为实体类并保存
            List<StkOrigDataCollect> withPriceRecords = commonService.convertBsToStkOrigDataCollect(finalWithPrice, true);
            List<StkOrigDataCollect> withoutPriceRecords = commonService.convertBsToStkOrigDataCollect(finalWithoutPrice, false);

            // 批量插入数据
            commonService.batchInsert(withPriceRecords);
            commonService.batchInsert(withoutPriceRecords);

            log.info("insertBs执行成功");

        } catch (Exception e) {
            log.error("处理报损数据失败", e);
            throw new RuntimeException("处理报损数据失败", e);
        }
    }

    /**
     * 添加价格
     */
    private Map<String, Object> addPrice(List<BsDataDTO> cutMainData, String endDate) {
        try {
            log.info("开始添加价格数据，价格日期: {}", endDate);
            Map<String, Object> result = new HashMap<>();

            List<BsDataDTO> PriceData = mataStkCustomsMapper.getBsPriceData().stream().filter(f -> f.getPrice() != null).collect(Collectors.toList());

            Map<String, List<BsDataDTO>> PriceDataMap = PriceData.stream().collect(Collectors.groupingBy(f -> f.getSku() + "|" + f.getPricebelongs()));

            //merge -->  mainData数据和plnPriceData数据
            List<BsDataDTO> mergeData = new ArrayList<>();
            for (BsDataDTO mainItem : cutMainData) {
                String key = mainItem.getSku() + "|" + mainItem.getAbbrbelongs();
                if (PriceDataMap.containsKey(key)) {
                    List<BsDataDTO> bsDataDTOS = PriceDataMap.get(key);
                    bsDataDTOS.forEach(f -> {
                        BsDataDTO newItem = new BsDataDTO();
                        BeanUtils.copyProperties(mainItem, newItem);
                        newItem.setInvoicedate(f.getInvoicedate());
                        newItem.setCurrency(f.getCurrency());
                        newItem.setQty(f.getQty());
                        newItem.setPrice(f.getPrice());
                        newItem.setPricebelongs(f.getPricebelongs());
                        mergeData.add(newItem);
                    });
                } else {
                    mergeData.add(mainItem);
                }
            }

            List<BsDataDTO> withPriceData = mergeData.stream().filter(f -> f.getPrice() != null).collect(Collectors.toList());

            if (endDate.equals("inoutdate")) {
                withPriceData.forEach(f -> f.setDateDiffer(ChronoUnit.DAYS.between(f.getInvoicedate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), f.getInoutDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate())));
            } else {
                withPriceData.forEach(f -> f.setDateDiffer(ChronoUnit.DAYS.between(f.getInvoicedate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")))));
            }

            //完成了 日期的天数差值计算
            withPriceData = calculateDateAndGetFirstData(withPriceData);

            List<String> withPriceDataIndexList = withPriceData.stream().map(BsDataDTO::getIndex).collect(Collectors.toList());

            List<BsDataDTO> withoutPriceData = cutMainData.stream().filter(f -> !withPriceDataIndexList.contains(f.getIndex())).collect(Collectors.toList());

            result.put("withPrice", withPriceData);
            result.put("withoutPrice", withoutPriceData);
            log.info("添加价格数据完成，有价格数据: {} 条，无价格数据: {} 条", withPriceData.size(), withoutPriceData.size());
            return result;
        } catch (Exception e) {
            log.error("添加价格数据失败", e);
            throw new RuntimeException("添加价格数据失败", e);
        }
    }

    /**
     * 添加异常价格
     */
    private List<BsDataDTO> addAbnormalPrice(List<BsDataDTO> withoutPriceData, String endDate) {
        try {
            log.info("开始添加异常价格数据，价格日期: {}", endDate);

            List<BsDataDTO> PriceData = mataStkCustomsMapper.getBsPriceData().stream().filter(f -> f.getPrice() != null).collect(Collectors.toList());

            Map<String, List<BsDataDTO>> PriceDataMap = PriceData.stream().collect(Collectors.groupingBy(BsDataDTO::getSku));

            //merge -->  mainData数据和plnPriceData数据
            List<BsDataDTO> mergeData = new ArrayList<>();
            for (BsDataDTO mainItem : withoutPriceData) {
                String key = mainItem.getSku();
                if (PriceDataMap.containsKey(key)) {
                    List<BsDataDTO> bsDataDTOS = PriceDataMap.get(key);
                    bsDataDTOS.forEach(f -> {
                        BsDataDTO newItem = new BsDataDTO();
                        BeanUtils.copyProperties(mainItem, newItem);
                        newItem.setInvoicedate(f.getInvoicedate());
                        newItem.setCurrency(f.getCurrency());
                        newItem.setQty(f.getQty());
                        newItem.setPrice(f.getPrice());
                        newItem.setPricebelongs(f.getPricebelongs());
                        mergeData.add(newItem);
                    });
                } else {
                    mergeData.add(mainItem);
                }
            }

            //去除价格为空的记录
            List<BsDataDTO> abWithPriceData = mergeData.stream().filter(f -> f.getPrice() != null).collect(Collectors.toList());

            //计算differDate值
            if (endDate.equals("inoutdate")) {
                abWithPriceData.forEach(f -> f.setDateDiffer(ChronoUnit.DAYS.between(f.getInvoicedate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),f.getInoutDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate())));
            } else {
                abWithPriceData.forEach(f -> f.setDateDiffer(ChronoUnit.DAYS.between(f.getInvoicedate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")))));
            }

            //完成了 日期的天数差值计算
            abWithPriceData = calculateDateAndGetFirstData(abWithPriceData);

            log.info("添加异常价格数据完成，处理数据: {} 条", abWithPriceData.size());
            return abWithPriceData;
        } catch (Exception e) {
            log.error("添加异常价格数据失败", e);
            throw new RuntimeException("添加异常价格数据失败", e);
        }
    }

    /**
     * 计算日期差值并根据条件排序分组取得第一条记录
     */
    private static List<BsDataDTO> calculateDateAndGetFirstData(List<BsDataDTO> withPriceData) {
        withPriceData = withPriceData.stream().filter(f -> f.getDateDiffer() > 0).collect(Collectors.toList());

        // 按照日期差、数量、出口价格排序，然后按cpbh和index(sheetNumber+direction)分组，取每组第一条记录
        Map<String, List<BsDataDTO>> groupedData = withPriceData.stream().sorted(Comparator.comparing(BsDataDTO::getDateDiffer, Comparator.nullsLast(Comparator.naturalOrder())).thenComparing(BsDataDTO::getQty, Comparator.nullsLast(Comparator.reverseOrder())).thenComparing(BsDataDTO::getPrice, Comparator.nullsLast(Comparator.reverseOrder()))).collect(Collectors.groupingBy(f -> f.getSku() + f.getInoutDate() + f.getIndex()));

        // 取每组第一条记录
        Map<String, BsDataDTO> withPriceDataMap = new HashMap<>();
        for (String key : groupedData.keySet()) {
            List<BsDataDTO> group = groupedData.get(key);
            if (!withPriceDataMap.containsKey(key) && !group.isEmpty()) {
                withPriceDataMap.put(key, group.get(0));
            }
        }

        withPriceData = new ArrayList<>(withPriceDataMap.values());
        return withPriceData;
    }







}